
L.FocusMarker = L.Path.extend({

  initialize: function (latlng, options) {
    L.setOptions(this, options);
    if (latlng === undefined) {
      throw Error('Please give a valid lat/lon-position');
    }
    options = options || {};
    this._id = options.trackId || 0;

    // if (this._id === '413438070') {
    //   console.log('marker 38070:', options);
    // }

    this._leaflet_id = this._id + 'FM';
    this._latlng = L.latLng(latlng);
  },

  /**
   * This function is empty but necessary
   * because it is called during the rendering process of Leaflet v1.0.
   * @method _project
   */
  _project: function () {
  },

  /**
   * Update the path
   * This function is called during the rendering process of leaflet v1.0
   * @method _update
   */
  _update: function () {
    this._setPath();
  },

  /**
   * Sets the contents of the d-attribute in a path-element of an svg-file.
   * @method _setPath
   */
  _setPath: function () {
    this._path.setAttribute('d', this.getPathString());
  },

  setData: function (data) {
    var oldLatLng = this._latlng;
    this._latlng = L.latLng({lat: data.latitude, lng: data.longitude});

    this.fire('move', {oldLatLng: oldLatLng, latlng: this._latlng});
    return this.redraw();
  },

  /**
   * Set latitude/longitude on the symbol.
   * @method setLatLng
   * @param latlng {LatLng} Position of the symbol on the map.
   */
  setLatLng: function (latlng) {
    var oldLatLng = this._latlng;
    this._latlng = L.latLng(latlng);
    this.fire('move', {oldLatLng: oldLatLng, latlng: this._latlng});
    return this.redraw();
  },

  /**
   * Returns the trackId.
   * @method getTrackId
   * @return {Number} The track id.
   */
  getTrackId: function () {
    return this._id;
  },

  _getLatSize: function () {
    return this._getLatSizeOf(this._size);
  },

  _getLngSize: function () {
    return this._getLngSizeOf(this._size);
  },

  _getLatSizeOf: function (value) {
    return (value / 40075017) * 360;
  },

  _getLngSizeOf: function (value) {
    return ((value / 40075017) * 360) / Math.cos((Math.PI / 180) * this._latlng.lat);
  },

  /**
   * Returns the bounding box of the symbol.
   * @method getBounds
   * @return {LatLngBounds} The bounding box.
   */
  getBounds: function () {
    var lngSize = this._getLngSize() / 2.0;
    var latSize = this._getLatSize() / 2.0;
    var latlng = this._latlng;
    return new L.LatLngBounds(
      [latlng.lat - latSize, latlng.lng - lngSize],
      [latlng.lat + latSize, latlng.lng + lngSize]);
  },

  /**
   * Returns the position of the symbol on the map.
   * @mathod getLatLng
   * @return {LatLng} The position object.
   */
  getLatLng: function () {
    return this._latlng;
  },

  _getRectPath: function () {
    return this._makeRectPath(20)
  },

  _makeRectPath: function (r) {
    // var r = 20;
    var high = 10;
    var result = '';
    var center = this._map.latLngToLayerPoint(this._latlng);
    var x0 = center.x - r, x1 = center.x + r, y0 = center.y - r, y1 = center.y + r;
    var pts = [
      x0, y0 + high,
      x0, y0,
      x0 + high, y0,
      x1 - high, y0,
      x1, y0,
      x1, y0 + high,
      x1, y1 - high,
      x1, y1,
      x1 - high, y1,
      x0 + high, y1,
      x0, y1,
      x0, y1 - high
    ];
    for (var i = 0; i < pts.length; i += 2) {
      if ((i + 1) % 3 < 2) {
        result += 'M ' + pts[i] + ' ' + pts[i + 1] + ' ';
        result += 'L ' + pts[i + 2] + ' ' + pts[i + 3] + ' ';
      }
    }
    // result += 'M ' + x0 + ' ' + (y0 + high) + ' ';
    // result += 'L ' + x0 + ' ' + y0 + ' ';
    // result += 'M ' + x0 + ' ' + y0 + ' ';
    // result += 'L ' + (x0 + high) + ' ' + y0 + ' ';
    return result
  },

  /**
   * Generates the symbol as SVG path string.
   * depending on zoomlevel or track heading different symbol types are generated.
   * @return {String} The symbol path string.
   */
  getPathString: function () {
    return this._getRectPath();
  }
});

/**
 * Factory function to create the symbol.
 * @method trackSymbol
 * @param latlng {LatLng} The position on the map.
 * @param options {Object} Additional options.
 */
L.focusMarker = function (latlng, options) {
  return new L.FocusMarker(latlng, options);
};
